package com.dq.controller.api.login;

import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import com.dq.context.config.WxMaConfiguration;
import com.dq.controller.in.org.OrgLngQuery;
import com.dq.controller.in.request.EncryptedLogin;
import com.dq.domain.annex.MallAnnex;
import com.dq.domain.base.impl.BaseDaoImpl;
import com.dq.domain.org.Org;
import com.dq.domain.sys.section.SysSection;
import com.dq.domain.sys.user.user.WxUser;
import com.dq.domain.sys.user.user.base.SysUser;
import com.dq.exception.customException.AdminException;
import com.dq.service.AllService;
import com.dq.service.section.SysSectionService;
import com.dq.shiro.MyToken;
import com.dq.vo.ListDataVo;
import com.dq.vo.Vo;
import com.dq.vo.baseVo.VO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.java.Log;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author liuhui
 * @date 2019/9/16 0016 10:17:31
 */
@RestController
@RequestMapping("/api/login")
@Api(description = "登陆")
@Log
public class ApiLoginController extends AllService {


    @ApiOperation("小程序授权登陆")
    @GetMapping("/small/{code}")
    public Vo userInfo(@PathVariable @ApiParam("小程序返回code码") String code) throws AdminException {
        HashMap<String, Object> map = new HashMap<>();
        try {
            WxMaJscode2SessionResult wxMaJscode2SessionResult = WxMaConfiguration.getWxMaService().jsCode2SessionInfo(code);
            map.put("sessionKey", wxMaJscode2SessionResult.getSessionKey());
            map.put("openId", wxMaJscode2SessionResult.getOpenid());
            map.put("unionid", wxMaJscode2SessionResult.getUnionid());
            if (StringUtils.isNotBlank(wxMaJscode2SessionResult.getOpenid())) {
                WxUser user = wxUserRepository.findByOpenidAndDeletedFalse(wxMaJscode2SessionResult.getOpenid());
                if (null == user) {
                    map.put("isExist", false);
                    map.put("user", null);
                } else {
                    //已经存在了
                    String token = tokenService.createToken(user);
                    Subject subject = SecurityUtils.getSubject();
                    AuthenticationToken token1 = new MyToken(token);
                    subject.login(token1);
                    WxUser.Vo sysUserVO = (WxUser.Vo) user.toVO();
                    sysUserVO.setToken(token);
                    map.put("isExist", true);
                    map.put("user", sysUserVO);
                }
            } else {
                throw new AdminException("获取用户信息失败");
            }
            return new Vo(map);
        } catch (WxErrorException e) {
            throw new AdminException("获取用户信息失败");
        }
    }

    /**
     * 登陆逻辑
     * @param encryptedLogin
     * @return
     * @throws AdminException
     */
    @PostMapping("/encryptedLogin")
    @ApiOperation("解密登陆")
    public Vo encrytedLogin(@RequestBody EncryptedLogin encryptedLogin) throws AdminException {
        log.info("登陆传入信息：" + encryptedLogin);
        WxMaPhoneNumberInfo wxMaPhoneNumberInfo = WxMaConfiguration.getMaUserService().getPhoneNoInfo(encryptedLogin.getSessionKey(), encryptedLogin.getEncryptedData(), encryptedLogin.getIvStr());
        if (null == wxMaPhoneNumberInfo) {
            throw new AdminException("授权失败");
        }
        log.info("获取手机号信息：" + wxMaPhoneNumberInfo);
        WxUser queryUser = wxUserRepository.getByOpenid(encryptedLogin.getOpenId());
        WxUser saveUser = null;
        //判断系统之前是否添加过此电话的用户
        if (null == queryUser) {
            //注册用户，添加邀请上级关系、添加会员所属门店
            //邀请人user
            WxUser inviterUser = null;
            //邀请人门店
            SysSection ofOrg = null;
            if (StringUtils.isNotBlank(encryptedLogin.getInviterPhone())) {
                //查询微信所有用户 包括已删除
                WxUser user = wxUserRepository.getByUsername(encryptedLogin.getInviterPhone());
                if (null != user) {
                    inviterUser = user;
                }
                //用户绑定到
                if (null != inviterUser.getSection()) {
                    ofOrg = inviterUser.getSection();
                }
            }
            WxUser user = new WxUser();
            if (StringUtils.isNotBlank(encryptedLogin.getUnionid())) {
                user.setUnionid(encryptedLogin.getUnionid());
            }
            user.setHeadImg(encryptedLogin.getHeadImg());
            user.setOpenid(encryptedLogin.getOpenId());

            user.setUsername(encryptedLogin.getNickName());
            user.setLocalNickName(encryptedLogin.getNickName());
            user.setUserRealcName(encryptedLogin.getNickName());

            user.setMobile(wxMaPhoneNumberInfo.getPurePhoneNumber());
            user.setInviteUser(inviterUser);
            user.setStatus(SysUser.Status.on);
            user.setShareCode(SysUser.generateShortUuid());
            user.setInviteTime(System.currentTimeMillis());
            user.setSection(ofOrg);
            user.setEntryTime(System.currentTimeMillis());
            user.setCustomerType(WxUser.CustomerType.active);
            user.setMemberType(WxUser.MemberType.experience);
            saveUser = wxUserRepository.save(user);
        } else {
            if (StringUtils.isBlank(wxMaPhoneNumberInfo.getPhoneNumber())) {
                queryUser.setUsername(wxMaPhoneNumberInfo.getPhoneNumber());
                saveUser = wxUserRepository.save(queryUser);
            }else{
                saveUser = queryUser;
            }
        }
        saveUser.setInviteUser(saveUser.getInviteUser());
        String token = tokenService.createToken(saveUser);
        Subject subject = SecurityUtils.getSubject();
        AuthenticationToken token1 = new MyToken(token);
        subject.login(token1);
        WxUser.Vo sysUserVO = (WxUser.Vo) saveUser.toVO();
        sysUserVO.setToken(token);
        return new Vo(sysUserVO);
    }


    @ApiOperation("模拟登录")
    @GetMapping("/simulation/{userId}")
    public Vo simulation(@PathVariable Long userId) throws AdminException {
        SysUser sysUser = dao.get(SysUser.class, userId);
        String token = tokenService.createToken(sysUser);
        Subject subject = SecurityUtils.getSubject();
        AuthenticationToken token1 = new MyToken(token);
        subject.login(token1);

        return new Vo(token);
    }

    @ApiOperation("用户登录后绑定门店")
    @PostMapping("/bindOrg/{orgId}")
    public Vo BindOrg(@PathVariable Long orgId) throws AdminException{
        WxUser wxUser = (WxUser) sysUserService.getUser();
        SysSection sysDept = dao.get(SysSection.class,orgId);
        if(sysDept == null){
            throw new AdminException("门店信息异常");
        }
        wxUser.setSection(sysDept);
        wxUserRepository.save(wxUser);
        return new Vo(HttpStatus.OK);
    }


    @Autowired
    private SysSectionService sectionService;
    @ApiOperation("获取最近店铺列表")
    @PostMapping("/orgListByLng")
    public ListDataVo orgListByLng(@Valid @RequestBody OrgLngQuery orgLngQuery) throws AdminException {
        List<Org> list = new ArrayList<>();
        List<Long> orgList = sectionService.listByLng(orgLngQuery.getLat(), orgLngQuery.getLng());
        for (Long aLong : orgList) {
            Org org = dao.get(Org.class, aLong);
            list.add(org);
        }

//        StringBuilder ids = new StringBuilder();
//        for (Long aLong : orgList) {
//            ids.append(aLong).append(",");
//        }
//        if(ids.toString().length() > 0) {
//            list = dao.find(String.format("select u from Org u where 1=1  and u.deleted = false and u.id in (%s) order by u.sort desc ", ids.toString().substring(0, ids.toString().length()-1)));
//        }

        return new ListDataVo((List<Org.Vo>) VO.toVOCollection(list));
    }
}
